package rainy.file.synchronization.server;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import rainy.file.synchronization.config.RainyRunTime;
import rainy.file.synchronization.server.commond.Command;
import rainy.file.synchronization.server.commond.CommondExecutor;
import rainy.file.synchronization.server.commond.exec.FileTransCommandExecutor;
import rainy.file.synchronization.server.commond.exec.HealthCheckCommandExecutor;
import rainy.file.synchronization.server.commond.exec.TailCommondExecutor;
import rainy.file.synchronization.server.file.TailerAppender;

/**
 * 
 * @author Grom
 *
 */
public class MonitorServerHandler extends SimpleChannelInboundHandler<String> {

	private static final Map<String, CommondExecutor> executorContainer = new HashMap<>();

	static {
		FileTransCommandExecutor fileExec = new FileTransCommandExecutor();
		executorContainer.put(fileExec.supportedCommond(), fileExec);
		HealthCheckCommandExecutor healthExec = new HealthCheckCommandExecutor();
		executorContainer.put(healthExec.supportedCommond(), healthExec);
		TailCommondExecutor tailExec = new TailCommondExecutor();
		executorContainer.put(tailExec.supportedCommond(), tailExec);
	}

	public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

	@Override
	public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
		Channel incoming = ctx.channel();
		for (Channel channel : channels) {
			channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " joined\n");
		}
		channels.add(ctx.channel());
	}

	@Override
	public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
		Channel incoming = ctx.channel();
		for (Channel channel : channels) {
			channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " Left\n");
		}
		channels.remove(ctx.channel());
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		Channel incoming = ctx.channel();
		System.out.println("client " + incoming.remoteAddress() + " online");
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		Channel incoming = ctx.channel();
		System.out.println("client " + incoming.remoteAddress() + " outLine");
	}

	private String folder = RainyRunTime.getPropDefine("rainy.master.target.folder");

	/**
	 * 服务器端写入本地文件的逻辑
	 */
	protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
		Channel incoming = ctx.channel();
		String key = msg.substring(0, msg.indexOf(RainyRunTime.COMMAND_CONTENT_SPLIT));
		if (executorContainer.containsKey(key)) {
			CommondExecutor<String> exec = executorContainer.get(key);
			Command<String> command = new Command<>();
			command.setFullContent(msg);
			command.commondType = key;
			exec.executeCommand(command);
			return;
		}
		/**
		 * 处理原来的文件传输的逻辑暂时不处理
		 */
		if (msg.indexOf("#") > 0) {
			// 集成原来的file功能
			CommondExecutor<String> exec = executorContainer.get(RainyRunTime.COMMOND_FILE);
			Command<String> command = new Command<>();
			command.setFullContent(msg);
			command.commondType = RainyRunTime.COMMOND_FILE;
			exec.executeCommand(command);
			return;
			// oldFileTransfer(msg, incoming);
		}
	}

	/**
	 * 该部分可以协助监控客户端出现错误
	 */
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		Channel incoming = ctx.channel();
		System.out.println("client " + incoming.remoteAddress() + " 异常");
		// 当出现异常就关闭连接
		cause.printStackTrace();
		ctx.close();
	}

}